/*
 * ring_buffer.c
 *
 *  Created on: Aug 19, 2024
 *      Author: 31652
 */

#include <ring_buffer.h>

#define Next_Location(cur, n, capacity) (cur+n)%capacity

void _I_Move_Head_Next(i_ringbuffer* handle, uint32_t n);
void _I_Move_Tail_Next(i_ringbuffer* handle, uint32_t n);

uint8_t I_Ring_Buffer_Init(i_ringbuffer* instance, uint8_t* dataBuffer, uint32_t capacity) {
	if (capacity < 2) {
		return I_RING_BUFFER_ERROR;
	}
	instance->capacity = capacity;
	instance->data = dataBuffer;
	instance->head = 0;
	instance->tail = 0;
	instance->size = 0;
	return I_RING_BUFFER_SUCCESS;
}

void I_Ring_Buffer_Skip(i_ringbuffer* handle, uint32_t n) {
	if (handle->size <= n) {
		// change to empty
		I_Ring_Buffer_Clear(handle);
	} else {
		// head move forward n
		_I_Move_Head_Next(handle, n);
		handle->size -= n;
	}
}
void I_Ring_Buffer_Clear(i_ringbuffer* handle) {
	handle->head = handle->tail;
	handle->size = 0;
}

uint8_t I_Ring_Buffer_IsEmpty(i_ringbuffer* handle) {
	if (handle->head == handle->tail) {
		return I_RING_BUFFER_SUCCESS;
	} else {
		return I_RING_BUFFER_ERROR;
	}
}

uint8_t I_Ring_Buffer_IsFull(i_ringbuffer* handle) {
	if (handle->head == handle->tail) {
		return I_RING_BUFFER_SUCCESS;
	} else {
		return I_RING_BUFFER_ERROR;
	}
}

uint8_t I_Ring_Buffer_WriteBytes(i_ringbuffer* handle, uint8_t* input, uint32_t n) {
	uint32_t halfSize = 0;
	if (n == 0) { // 没数据什么也不做
		return I_RING_BUFFER_SUCCESS;
	}
	if (I_Ring_Buffer_FreeSpace(handle) < n) { // 空间不足
		return I_RING_BUFFER_ERROR;
	}
	if (handle->capacity <= handle->tail+n) {// 超出环尾
		halfSize = handle->capacity-handle->tail;
		memcpy(handle->data+handle->tail, input, halfSize); // tail to capacity
		memcpy(handle->data, input + halfSize, n - halfSize); // 0 to n -
	} else {// 全量复制
		memcpy(handle->data + handle->tail, input, n);
	}
	_I_Move_Tail_Next(handle, n);
	handle->size += n;
	return I_RING_BUFFER_SUCCESS;
}

uint8_t I_Ring_Buffer_ReadBytes(i_ringbuffer* handle, uint8_t* output, uint32_t n) {
	uint32_t halfSize = 0;
	if (n == 0) { // 没数据什么也不做
		return I_RING_BUFFER_SUCCESS;
	}
	if (handle->size < n) { // 数量不足
		return I_RING_BUFFER_ERROR;
	}
	if (handle->capacity <= handle->head+n) {// 超出环尾
		halfSize = handle->capacity-handle->head;
		memcpy(output, handle->data+handle->head, halfSize); // tail to capacity
		memcpy(output + halfSize, handle->data, n - halfSize); // 0 to n -
	} else {// 全量复制
		memcpy(output, handle->data + handle->head, n);
	}
	_I_Move_Head_Next(handle, n);
	handle->size -= n;
	return I_RING_BUFFER_SUCCESS;
}

uint8_t I_Ring_Buffer_GetByte(i_ringbuffer* handle, uint32_t offset) {
	return handle->data[(handle->head+offset) % handle->capacity];
}

uint32_t I_Ring_Buffer_FreeSpace(i_ringbuffer* handle) {
	return handle->capacity - handle->size;
}


void _I_Move_Tail_Next(i_ringbuffer* handle, uint32_t n) {
	handle->tail = Next_Location(handle->tail, n, handle->capacity);
}

void _I_Move_Head_Next(i_ringbuffer* handle, uint32_t n) {
	handle->head = Next_Location(handle->head, n, handle->capacity);
}

void I_Ring_Status(i_ringbuffer* handle) {
	int i;
	printf("RB info:\t head:%ld-->tail:%ld\t space:%ld(%ld)\n", handle->head, handle->tail, handle->size, handle->capacity);
	printf("buffer:<");
	if (handle->tail < handle->head) {
		for (i=0; i + handle->head < handle->capacity; i++) {
			printf("%02x ", handle->data[handle->head+i]);
		}
		for (i=0; i < handle->tail; i++) {
			printf("%02x ", handle->data[i]);
		}
	} else {
		for (i=0; i<handle->size; i++) {
			printf("%02x ", handle->data[handle->head+i]);
		}
	}
	printf(">\n");
}

void I_Ring_Ram(i_ringbuffer* handle) {
	int i;
	printf("ram:<");
	for (i=0; i<handle->capacity; i++) {
		printf("%02x ", handle->data[i]);
	}
	printf(">\n");
}
